<template>
	<view>
		<view class="search">
			<view class="search_box">
				<image src="@/static/image/search.png" class="image_one"></image>
				<input type="text" confirm-type="search" v-model="keyname" @input="changeInput"  @confirm="searchClickname(keyname)"/>
				<image src="@/static/image/del.png" @click="delkeyname"></image>
			</view>
			<view class="search_btn" @click="searchClickname(keyname)">搜索</view>
		</view>
		<view class="bottom">
			<!-- 搜索关键词列表 -->
			<view class="keyword-list-box" v-show="showSearchList&&keyname!=''">
				<view class="keyword-entry" hover-class="keyword-entry-tap" v-for="(item,id) in drawKeyname()" :key="id" @click="searchClick(item)">
					<image class="image_three" src="@/static/image/search.png"></image>
					<rich-text :nodes="item.highlightedMname"></rich-text>
				</view>
			</view>
			<!-- 历史记录-->
			<view>
				<view class="history">
					<view class="title">
						<text style="font-size: 28rpx;">历史记录</text>
						<image class="image_two" src="@/static/image/del.png" @click="delsearchList"></image>
					</view>
					<view>
						<view class="item_box">
							<view class="item"  v-for="(historyItem, index) in searchList" :key="index" @click="searchClickname(historyItem)">
                <text class="item_text">{{historyItem}}</text>
              </view>
						</view>
					</view>
					<view v-if="searchList.length === 0" style="font-size: 26rpx; color: #ccc;">暂无搜索记录</view>
				</view>
			</view>
		</view>
	</view>
</template>
 
<script>
export default {
	data() {
		return {
      keyname:'',
      defaultkeyname:'',
      keynameList:[],
      medicineList:[],
      showSearchList:false,
      searchList: uni.getStorageSync('searchHistory') || []
      
		}
	},
  onHide() {
     uni.setStorageSync('searchHistory', this.searchList);
  },
  onLoad(){
    this.loadList();
  },
  //钩子函数，退回此页面清除搜索框的内容
  onShow(){
    this.keyname='';
    this.showSearchList = false;
  },
  
	methods: {
    //删除搜索框的内容
    delkeyname(){
      this.keyname='';
    },
    //删除搜索记录
    delsearchList(){
      uni.removeStorageSync('searchHistory')
      this.searchList = [];
    },
    //添加搜索记录
    addToHistory(keyword){
      if(!this.searchList.includes(keyword)){
        this.searchList.unshift(keyword);
      }
    },
     isHTMLFragmentValid(htmlFragment) {
      // 简单检查是否有未闭合的标签
      let stack = [];
      let tags = htmlFragment.match(/<[^>]+>/g);
      if (!tags) {
          return true; // 没有标签，认为是有效的纯文本
      }
      for (let tag of tags) {
          if (tag.startsWith("<") && tag.endsWith(">")) {
              let tagName = tag.substring(1, tag.length - 1).split(" ")[0];
              if (tag.startsWith("</")) {
                  if (stack.pop()!== tagName) {
                      return false;
                  }
              } else {
                  stack.push(tagName);
              }
          } else {
              return false;
          }
      }
      return stack.length === 0;
  },
  escapeSpecialChars(str) {
      return str.replace(/[&<>"'\/]/g, function (char) {
          return {
              '&': '&amp;',
              '<': '&lt;',
              '>': '&gt;',
              '"': '&quot;',
              "'": '&#39;',
              '/': '&#x2F;'
          }[char];
      });
  },
    //收索列表跳转函数，高亮状态显示
    drawKeyname() {
        const currentInput = this.keyname;
        const newKeywordList = [];
    
        if (!currentInput) {
            // 如果输入框为空，直接返回原keynameList（可能为空数组）
            return this.keynameList;
        }
    
        this.keynameList.forEach((item) => {
            const mname = item.mname;
            const inputLowerCase = currentInput.toLowerCase();
            const mnameLowerCase = mname.toLowerCase();
    
            // 查找输入内容在关键词中的所有匹配位置及长度
            let matchInfos = [];
            let startIndex = 0;
            while (true) {
                const index = mnameLowerCase.indexOf(inputLowerCase, startIndex);
                if (index === -1) {
                    break;
                }
                // 记录匹配的起始位置和长度
                matchInfos.push({
                    start: index,
                    length: currentInput.length
                });
                startIndex = 65006;
            }
    
            // 如果有匹配位置，进行高亮处理
            if (matchInfos.length > 0) {
                let highlightedMname = mname;
                let offset = 0;
    
                matchInfos.forEach((matchInfo) => {
                    const start = matchInfo.start + offset;
                    const end = start + matchInfo.length;
    
                    highlightedMname = highlightedMname.slice(0, start) +
                        `<span style='color: #008000;'>${mname.slice(start, end)}</span>` +
                        highlightedMname.slice(end);
    
                    offset += 28; // 假设<span style='color: #008000;'>的长度为28，用于调整后续匹配位置的偏移量
                });
    
                // 使用正则表达式去除<span>标签
                let highlightedMnameWithoutSpan = highlightedMname.replace(/<span style='color: #008000;'>/g, "");
                highlightedMnameWithoutSpan = highlightedMnameWithoutSpan.replace(/<\/span>/g, "");
                 if (!this.isHTMLFragmentValid(highlightedMname)) {
                        // 重新去除可能残留的标签相关字符
                        highlightedMnameWithoutSpan = highlightedMname.replace(/<[^>]*>/g, "");
                    }
    
                const tmpObj = {
                  ...item,
                    mname: highlightedMnameWithoutSpan,
                    highlightedMname: highlightedMname
                };
                newKeywordList.push(tmpObj);
            } else {
                // 如果没有匹配，直接添加原item到新列表
                newKeywordList.push(item);
            }
        });
    
        return newKeywordList;
    },
    //搜索记录的点击函数跳转
    searchClickname(keyname){
      this.keyname = keyname;
      let id = null;
      const matchedMedicine = this. medicineList.find((medicine) =>medicine.mname === keyname);
      if(matchedMedicine){
        id = matchedMedicine.id;
        // 添加搜索关键词到历史记录
        this.addToHistory(keyname);
        uni.navigateTo({
        url:'/pages/detail/detail?id='+id
      });
      }else{
        //若数据库中没有该药材
        uni.showToast({
          title:'未找到相关药材',
          icon:'none',
          duration:2000
        })
      }
      
      
    },
    searchClick(item){
      const id = item.id;
      this.keyname = item.mname;
      const matchedMedicine = this.medicineList.find((medicine) => medicine.mname === item.mname);
      if (matchedMedicine) {
      this.addToHistory(item.mname);
      uni.navigateTo({
        url:'/pages/detail/detail?id='+id
      });
    }else{
      uni.showToast({
        title:'未找到相关药材',
        icon:'none',
        duration:2000
      })
    }
    },
    changeInput(){
      const currentInput = this.keyname;
      if(!currentInput){
        this.keynameList = [];
        return;
      }
      
      const currentInputEscaped = this.escapeSpecialChars(currentInput);
      const filteredList = [];
      //input的防抖操作
    let timeoutId;

    // 清除之前可能存在的定时器，避免多次触发防抖逻辑时出现混乱
    if (timeoutId) {
        clearTimeout(timeoutId);
    }

    // 设置新的定时器，延迟执行筛选逻辑
    timeoutId = setTimeout(() => {
        this.medicineList.forEach((medicine) => {
          // 对药材名称进行预处理，转义特殊字符
          const medicineNameEscaped = this.escapeSpecialChars(medicine.mname);
          
            if (medicine.mname.includes(currentInput)) {
                filteredList.push(medicine);
            }
        });
        this.keynameList = filteredList;
    }, 200);
    this.showSearchList = currentInput?true:false;
    },
    //请求所有药材数据
    loadList() {
      this.$request.get('/medicines/selectAll')
        .then(res => {
          if (res && res.data) {
            this.medicineList = res.data;
          } else {
            console.error('No data received or data is not in expected format');
          }
        })
        .catch(error => {
          console.error('Error fetching data:', error);
        });
    }
		}
  }
</script>
 
<style>
.search {
	display: flex;
	align-items: center;
	height: 120rpx;
	padding-bottom: 30rpx;
	background-color: #f7f7f7;
	font-size: 26rpx;
	
	}
  .image_one {
		width: 18rpx;
		height: 31rpx;
		margin-left: 53rpx;
    }
	.search_box {
		display: flex;
		align-items: center;
		width: 600rpx;
		height: 60rpx;
		background-color: #ffffff;
		// box-shadow: 2rpx 2rpx 2rpx red;
		border-radius: 30rpx;
		margin: 0 12rpx 0 25rpx;
		padding-left: 18rpx;
    }
		image:nth-child(1) {
			margin: 0 18rpx 0 7rpx;
			width: 28rpx;
			height: 28rpx;
		}
		image:nth-child(3) {
			margin: 0 14rpx 0 auto;
			width: 31rpx;
			height: 31rpx;
		}
		input {
			height: 60rpx;
			// letter-spacing: 4rpx;
			line-height: 60rpx;
			color: #969696;
		}
	.search_btn {
		width: 96rpx;
		height: 52rpx;
		background-color: #fff;
		color: #008000;
		border-radius: 26rpx;
		line-height: 52rpx;
		text-align: center;
	}
.bottom {
	margin-top: -10rpx;
	border-radius: 24rpx 24rpx 0 0;
	background-color: #ffffff;
	overflow: hidden;
	// padding: 34rpx 36rpx 0;
}
 
.history {
	margin: 34rpx 0;
	padding: 0 36rpx;
  margin-bottom: 68rpx !important;
}
.title {
	display: flex;
	align-items: center;
	font-size: 30rpx;
	color: #262626;
	font-family: Pingfang-Bold;
	margin-bottom: 34rpx;
	font-weight: bold;
  }
	.image_two {
		width: 25rpx;
		height: 28rpx;
		margin: 0 6rpx 0 auto;
	}
.item_box {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	font-size: 26rpx;
  }
.item {
		display: flex;
		align-items: center;
		height: 48rpx;
		margin: 0 24rpx 24rpx 0;
		padding: 0 24rpx;
		line-height: 48rpx;
		border-radius: 24rpx;
		color: #333333;
		background-color: #f4f4f4;
	}
  .item_text{
    margin-left: 8rpx;
    font-size: 28rpx;
  }
.keyword-list-box {
	position: fixed;
	top: 120rpx;
	width: 750rpx;
	background-color: #fff;
	z-index: 1;
}
.keyword-entry-tap {
	background-color: #eee;
}
.keyword-entry {
	display: flex;
	align-items: center;
	height: 80rpx;
	font-size: 26rpx;
	color: #333;
	padding: 0 30rpx;
	border-bottom: solid 1rpx #f7f7f7;
  }
	.image_three {
		width: 29rpx;
		height: 30rpx;
		margin-right: 30rpx;
	}
	text {
		margin-left: auto;
		color: #777;
		font-size: 22rpx;
	}
</style>